/** 
* Copyright (C) 2012-2017 ZEEI Inc.All Rights Reserved.
* 项目名称：common
* 文件名称：TreeUtil.java
* 包  名 称：com.zeei.common.utils
* 文件描述：树工具类
* 创建日期：2017年8月3日上午9:39:11
* 
* 修改历史
* 1.0 sunqian 2017年8月3日上午9:39:11 创建文件
*
*/
package com.zeei.ems.base.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.zeei.ems.base.tree.BasicTreeNodeVO;
import com.zeei.ems.base.tree.TreeNodeVO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

/**
 * @类型名称：TreeUtil 
 * @类型描述：树工具类
 * @功能描述：提供树工具方法 
 * @创建作者：sunqian
 */
public class TreeUtil {

	public static <T extends BasicTreeNodeVO> List<TreeNodeVO<T>> buildTree(List<T> listData, String parentId) {
		List<TreeNodeVO<T>> rootList = new ArrayList<>();

		for (T vo : listData) {
			if (!StringUtils.isEmpty(parentId)) {
                if (parentId.equals(vo.getParentId())) {
					TreeNodeVO<T> node = new TreeNodeVO<T>();
					node.setId(vo.getId());
					node.setText(vo.getText());

					node.setData(vo);
					node.setChecked(vo.isCheck());
					createChildTreeNode(listData, node);
					rootList.add(node);
				}
			} else {
				if (StringUtils.isEmpty(vo.getParentId())) {
					TreeNodeVO<T> node = new TreeNodeVO<T>();
					node.setId(vo.getId());
					node.setText(vo.getText());

					node.setData(vo);
					node.setChecked(vo.isCheck());
					createChildTreeNode(listData, node);
					rootList.add(node);
				}
			}
		}

		return rootList;
	}

	private static <T extends BasicTreeNodeVO> void createChildTreeNode(List<T> listData, TreeNodeVO<T> node) {
		for (T vo : listData) {
			if (node.getId().equals(vo.getParentId())) {
				TreeNodeVO<T> childNode = new TreeNodeVO<T>();
				childNode.setId(vo.getId());
				childNode.setText(vo.getText());
				childNode.setParentId(vo.getParentId().toString());

				childNode.setData(vo);
				childNode.setChecked(vo.isCheck());
				createChildTreeNode(listData, childNode);
				node.addChildren(childNode);
			}
		}
	}

	/**
	 * 方法描述:构建一颗TreeNode的树
	 *
	 * @param listData
	 * @param id
	 *            节点id
	 * @return
	 */
	public static <T extends TreeNodeVO<T>> List<TreeNodeVO<T>> buildTreeNodeTree(List<T> listData, String id) {
		List<TreeNodeVO<T>> rootList = new ArrayList<TreeNodeVO<T>>();

		for (T vo : listData) {
			if (StringUtils.isNotEmpty(id)) {
				if (id.equals(vo.getId())) {
					createTreeNodeChild(listData, vo);
					rootList.add(vo);
				}
			} else {
				if (StringUtils.isEmpty(vo.getParentId()) || "0".equals(vo.getParentId()) || "d".equals(vo.getParentId())) {
					createTreeNodeChild(listData, vo);
					rootList.add(vo);
				}
			}
		}

		return rootList;
	}

	private static <T extends TreeNodeVO<T>> void createTreeNodeChild(List<T> listData, TreeNodeVO<T> node) {
		for (T vo : listData) {
			if (node.getId()!=null && vo.getParentId() !=null&&node.getId().equals(vo.getParentId())) {
				createTreeNodeChild(listData, vo);
				node.addChildren(vo);
			}
		}
	}

	/**
	 * 方法描述:设置关闭状态。
	 *
	 * @param treeList
	 */
	public static <T> void setInitCloseState(List<TreeNodeVO<T>> treeList) {
		for (TreeNodeVO<T> node : treeList) {
			if (CollectionUtils.isNotEmpty(node.getChildren())) {
				if (StringUtil.isEmpty(node.getParentId()) || "0".equals(node.getParentId())) {
					node.setState(TreeNodeVO.OPEN_STATE);
				} else {
					node.setState(TreeNodeVO.CLOSED_STATE);
				}
				setInitCloseState(node.getChildren());
			}
		}
	}

	/**
	 * 方法描述:将已有的树构建成一颗有搜索状态的树.
	 *
	 * @param searchNodelist
	 *            搜中的节点
	 * @param treeList
	 *            整颗树
	 * @return
	 */
	public static <T extends TreeNodeVO<T>> List<TreeNodeVO<T>> buildSearchTreeNodeTree(List<T> searchNodelist, List<TreeNodeVO<T>> treeList) {
		Map<String, TreeNodeVO<T>> tempMap = new HashMap<String, TreeNodeVO<T>>(searchNodelist.size());

		for (T vo : searchNodelist) {
			tempMap.put(vo.getId(), vo);
		}
		setInitCloseState(treeList);
		setSearchNode(tempMap, treeList);
		setSearchNodeOpenState(treeList);
		return treeList;
	}

	/**
	 * 方法描述:设置搜索的节点为打开状态。
	 *
	 * @param treeList
	 */
	private static <T> void setSearchNodeOpenState(List<TreeNodeVO<T>> treeList) {
		for (TreeNodeVO<T> node : treeList) {
			if (CollectionUtils.isNotEmpty(node.getChildren())) {
				if (hasSearchNode(node.getChildren())) {
					node.setState(TreeNodeVO.OPEN_STATE);
				}
				setSearchNodeOpenState(node.getChildren());
			}
		}
	}

	/**
	 * 方法描述:有搜索节点。[节点是搜索节点或者子树有搜索节点]
	 *
	 * @param treeList
	 * @return
	 */
	private static <T> boolean hasSearchNode(List<TreeNodeVO<T>> treeList) {
		for (TreeNodeVO<T> node : treeList) {
			if (node.isSearchNode()) {
				return true;
			}
			if (CollectionUtils.isNotEmpty(node.getChildren())) {
				if (hasSearchNode(node.getChildren())) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * 方法描述:设置搜索节点
	 *
	 * @param searchNodeMap
	 */
	private static <T extends TreeNodeVO<T>> void setSearchNode(Map<String, TreeNodeVO<T>> searchNodeMap, List<TreeNodeVO<T>> treeList) {

		for (TreeNodeVO<T> node : treeList) {
			if (searchNodeMap.get(node.getId()) != null) {
				node.setSearchNode(true);
			}
			if (CollectionUtils.isNotEmpty(node.getChildren())) {
				setSearchNode(searchNodeMap, node.getChildren());
			}
		}
	}

	/**
	 * 方法描述:构建一颗搜索节点TreeNode的树
	 *
	 * @param listData
	 * @param searchNodelist
	 *            包含搜索内容的节点
	 * @return
	 */
	public static <T extends TreeNodeVO<T>> List<TreeNodeVO<T>> buildSearchNodeTree(List<T> listData, List<T> searchNodelist) {
		List<TreeNodeVO<T>> rootList = new ArrayList<TreeNodeVO<T>>();

		if (searchNodelist != null && !searchNodelist.isEmpty()) {
			List<T> listRecord = new ArrayList<T>();
			Map<String, T> allRecordMap = new HashMap<String, T>();
			for (T record : listData) {
				allRecordMap.put(record.getId(), record);
			}
			// 查找过滤出来的节点和他们的父节点
			listRecord = getSelfAndTheirParentRecord(searchNodelist, new ArrayList<T>(), new HashMap<String, T>(), allRecordMap);
			rootList = buildTreeNodeTree(listRecord, null);
		}

		return rootList;
	}

	public static <T extends TreeNodeVO<T>> List<T> getSelfAndTheirParentRecord(List<T> parentList, List<T> resultList,
			Map<String, T> filterRecordMap, Map<String, T> allRecordMap) {
		// 当父节点为null或者节点数量为0时返回结果，退出递归
		if (parentList == null || parentList.size() == 0) {
			return resultList;
		}
		// 重新创建父节点集合
		List<T> listParentRecord = new ArrayList<T>();
		// 遍历已经过滤出来的节点
		for (T record : parentList) {

			String uuid = record.getId();
			String parent_uuid = record.getParentId();

			// 如果已经过滤出来的节点不存在则添加到list中
			if (!filterRecordMap.containsKey(uuid)) {
				listParentRecord.add(record);// 添加到父节点中
				filterRecordMap.put(uuid, record);// 添加到已过滤的map中
				allRecordMap.remove(uuid);// 移除集合中相应的元素
				resultList.add(record);// 添加到结果集中
			}

			// 找出本节点的父节点并添加到listParentRecord父节点集合中，并移除集合中相应的元素
			if (StringUtil.isNotEmpty(parent_uuid)) {
				T parentRecord = allRecordMap.get(parent_uuid);
				if (parentRecord != null) {
					listParentRecord.add(parentRecord);
					allRecordMap.remove(parent_uuid);
				}
			}

		}
		// 递归调用
		getSelfAndTheirParentRecord(listParentRecord, resultList, filterRecordMap, allRecordMap);

		return resultList;
	}
}
